/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tencent.tendon.convert.json;

import java.util.Collection;
import java.util.Map;

/**
 *
 * @author nbzhang
 */
public final class JsonAnyEncoder extends JsonEncoder<Object> {

    private static final JsonAnyEncoder instance = new JsonAnyEncoder();

    final JsonMapEncoder mapEncoder;

    final JsonCollectionEncoder collectionEncoder;

    private JsonAnyEncoder() {
        super(Object.class);
        this.simpled = false;
        this.mapEncoder = new JsonMapEncoder(Object.class, this, this);
        this.collectionEncoder = new JsonCollectionEncoder(Object.class, this);
    }

    public static JsonAnyEncoder getInstance() {
        return instance;
    }

    @Override
    public void convertTo(final JsonWriter out0, final Object value0) {
        final JsonWriter out = out0;
        final Object value = value0;
        if (value == null) {
            out.write('n', 'u', 'l', 'l');
            return;
        }
        final Class clazz = value.getClass();

        JsonEncoder printer = JsonFactory.findEncoder(clazz);
        if (printer != null) {
            printer.convertTo(out, value);
            return;
        }

        final JsonListener listener = JsonFactory.findListener(clazz);
        if (listener != null) {
            listener.convertTo(out, value);
            return;
        }
        if (clazz.isArray()) {
            final Class component = clazz.getComponentType();
            JsonEncodable encoder = JsonFactory.findListener(component);
            if (encoder == null) encoder = JsonFactory.findEncoder(component);
            if (encoder == null) encoder = JsonAnyEncoder.getInstance();
            if (encoder != null) {
                printer = new JsonArrayEncoder(clazz, component, encoder);
                if (encoder != JsonAnyEncoder.getInstance()) {
                    JsonFactory.register(clazz, printer);
                }
                printer.convertTo(out, value);
                return;
            }
        }
        if (Collection.class.isAssignableFrom(clazz)) {
            collectionEncoder.convertTo(out, value);
            return;
        }
        if (Map.class.isAssignableFrom(clazz)) {
            mapEncoder.convertTo(out, value);
            return;
        }
        if (clazz.getName().indexOf("java.") == 0 || clazz.getName().indexOf("javax.") == 0) {
            out.write('"');
            out.write(String.valueOf(value).toCharArray());
            out.write('"');
            return;
        }
        JsonFactory.loadEncoder(clazz).convertTo(out, value);
    }
}
